<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/polymer/lib/elements/custom-style.html">
<link rel="import" href="../../bower_components/vaadin-material-theme/vaadin-combo-box.html">
<link rel="import" href="../../bower_components/vaadin-material-theme/vaadin-dialog.html">
<link rel="import" href="../view-app.html">
<link rel="import" href="../style/shared-styles.html">
<script src="../utilizes/formatDate.js"></script>

<dom-module id="view-track-production">
    <template>
        <style include="shared-styles app-grid-style">
            :host {
                display: block;
                margin: 10px;
            }

            @media (min-width: 360px) and (max-width: 768px) {
                :host {
                    --app-grid-columns: 1;
                }
            }

            @media (min-width: 769px) and (max-width: 1024px) {
                :host {
                    --app-grid-columns: 1;
                }
            }

            @media (min-width: 1025px) and (max-width: 1200px) {
                :host {
                    --app-grid-columns: 2;
                }
            }

            @media (min-width: 1201px) and (max-width: 2560px) {
                :host {
                    --app-grid-columns: 4;
                }
            }

            .flex-container {
                display: flex;
                align-content: center;
                justify-content: space-between;
                flex-flow: row nowrap;
            }

            .station-btn {
                margin: 5px;
                width: 200px;
            }

            .card-item {
                margin: 10px;
                padding: 20px;
                border: 1px solid rgba(0, 0, 0, .10);
                border-radius: 5px;
            }

            .card-item p {
                margin: 10px 0;
            }

            .card-item h1 {
                text-align: center;
            }

            .card-item-info-group {
                margin-bottom: auto;
            }

            .big-btn button {
                width: 400px;
                height: 100px;
                font-size: 2rem;
                display: block;
                font-size: 1.75rem;
                font-weight: 300;
            }

            .big-btn {
                margin: 10px 0 20px 0;
            }

            .main-card {
                margin-top: 26px;
            }

            p.card-item-title {
                font-weight: 500;
            }
        </style>

        <firebase-auth app-name="smart-mes" id="auth" user="{{user}}"></firebase-auth>
        <firebase-document app-name="smart-mes" id="userData" path="/user/[[user.uid]]" data="{{k}}"></firebase-document>
        <firebase-query app-name="smart-mes" id="trackingQuery" path="/data/[[k.key]]/trackingData" order-by-child="job_station"
            data="{{trackingItems}}"></firebase-query>
        <firebase-query app-name="smart-mes" id="orderQuery" path="/data/[[k.key]]/orderData" order-by-child="order_no" data="{{orderItems}}"></firebase-query>
        <firebase-query app-name="smart-mes" id="warehouseQuery" path="/data/[[k.key]]/warehouseData" order-by-child="order_no" data="{{warehouseItems}}"></firebase-query>
        <firebase-query app-name="smart-mes" id="stationQuery" path="/data/[[k.key]]/factoryData/station" data="{{stationItems}}"></firebase-query>
        <firebase-query app-name="smart-mes" id="deviceQuery" path="/data/[[k.key]]/factoryData/device" data="{{deviceItems}}"></firebase-query>
        <firebase-query app-name="smart-mes" id="commitQuery" path="/data/[[k.key]]/commitData"></firebase-query>
        <app-localstorage-document key="app-lang" data="{{language}}"></app-localstorage-document>
        <div class="card main-card">
            <h1 class="title">{{localize('work-in-progress-job-tracking')}}</h1>
            <div class="center">
                <iron-selector selected="{{selectedStation}}" attr-for-selected="name" fallback-selection="1" role="navigation">
                    <template is="dom-repeat" items="[[stationItems]]" as="stationItem">
                        <paper-button class="station-btn" name$="[[stationItem.st_number]]">
                            {{localize('station')}} [[stationItem.st_number]]
                        </paper-button>
                    </template>
                </iron-selector>
            </div>

            <div class="center">
                <h1 hidden$="[[isEmptyJobs(trackingItems.length)]]">No Job in Tracking</h1>
            </div>
            <ul class="app-grid">
                <template is="dom-repeat" filter="{{filterByStation(selectedStation)}}" items="{{trackingItems}}" index-as="job_status" as="item">
                    <li>
                        <div class="card-item">
                            <div class="card-item-info-group">
                                <h2 class="title">{{localize('part')}} [[item.job_part]]</h2>
                                <p style$="color:[[item.order_color]]">{{localize('order-number')}}: [[item.order_no]]</p>
                                <p>Job ID: [[item.job_id]]</p>
                                <p>{{localize('quantity')}}: [[item.job_quantity]] {{localize('item')}} </p>
                                <p>{{localize('product-name')}}: [[item.order_product]]</p>
                                <p>{{localize('sku-code')}}: [[item.job_sku]]</p>
                                <p>Dependency: [[item.job_dependency]]</p>
                                <p>{{localize('est-start')}}: [[timestampToTime(item.start)]]</p>
                                <p>{{localize('est-end')}}: [[timestampToTime(item.end)]]</p>
                                <p>{{localize('actual-start')}}: [[timestampToTime(item.actual_start)]]</p>
                                <p>{{localize('actual-end')}}: [[timestampToTime(item.actual_end)]]</p>
                                <p>{{localize('duration')}}: [[getActualDuration(item.actual_start,item.actual_end)]]</p>
                                <p>{{localize('defect')}}: [[item.job_defect]] {{localize('item')}} </p>
                                <p>{{localize('done')}}: [[item.job_good]] / [[item.job_quantity]]</p>
                                <p>Completed: [[getCompleteProgress(item.job_good,item.job_quantity)]] &#37;</p>
                                <p>{{localize('count')}}: [[getDeviceCounter(item,item.job_quantity,selectedDevice)]]</p>
                                <p>{{localize('status')}}:
                                    <span class$="[[getTextStatus(item.job_status)]]" style$="color:[[getColorStatus(item.job_status)]]">[[item.job_status]]</span>
                                </p>
                            </div>
                            <vaadin-combo-box label="{{localize('sensor')}}" items="[[deviceItems]]" item-value-path="name" item-label-path="name" loading="[[!deviceItems]]"
                                selected-item="{{selectedDevice}}" value="{{item.job_sensor}}" always-float-label>
                                <template>
                                    <paper-item>
                                        <paper-item-body two-line style="min-height: 0">
                                            <div>[[item.name]]</div>
                                            <div secondary>[[item.type]]</div>
                                        </paper-item-body>
                                    </paper-item>
                                </template>
                            </vaadin-combo-box>
                            <paper-button class="btn" on-click="receiveJob" disabled$="[[isDoneOrWIP(item.job_status)]]" job="[[item]]">
                                {{localize('receive-job')}}
                            </paper-button>
                            <paper-button class="btn shamrock" on-click="openJobDialog" job="[[item]]" disabled$="[[isDone(item.job_status)]]">
                                Progress Report
                            </paper-button>
                            <paper-button class="thunderbird btn" on-click="removeJob" job="[[item]]">
                                {{localize('remove')}}
                            </paper-button>
                        </div>
                    </li>
                </template>
            </ul>
        </div>
        <div class="card main-card">
            <h1 class="title">{{localize('tracking-device-management')}}</h1>
            <ul class="app-grid">
                <template is="dom-repeat" items="{{deviceItems}}" as="device">
                    <li hidden="[[device.hide]]">
                        <div class="card-item">
                            <div class="card-item-info-group">
                                <h2 class="title">[[device.name]]</h2>
                                <p>{{localize('type')}}: [[device.type]]</p>
                                <p>{{localize('machine')}}: [[device.machine]]</p>
                                <p>{{localize('count')}}: [[device.counter]]</p>
                                <p>{{localize('updated')}}: [[timestampToTime(device.update)]]</p>
                            </div>
                            <paper-toggle-button class="switch" checked="[[device.enable]]" id="deviceControlSwitch" noink> {{localize('enabled')}}</paper-toggle-button>
                            <paper-button class="btn" on-click="resetCounter" device="[[device]]">
                                {{localize('reset')}}
                            </paper-button>
                            <paper-button class="btn" on-click="_openEditMachineCard" device="[[device]]">
                                {{localize('edit')}}
                            </paper-button>
                            <paper-button class="thunderbird btn" on-click="removeDevice" device="[[device]]">
                                {{localize('remove')}}
                            </paper-button>
                        </div>
                    </li>
                </template>
            </ul>
            <div class="center">
                <paper-button class="big-btn" on-click="openAddDeviceCard">
                    Add Device
                </paper-button>
            </div>
        </div>
        <vaadin-dialog id="reportJobDialog" class="dialog">
            <template>
                <custom-style>
                    <style include="view-settings">
                        :host {
                            max-width: 500px;
                            margin-top: 100px;
                            --app-background-color: transpalent;
                            --paper-input-container-focus-color: var( --app-primary-color);
                        }

                        [part="content"] {
                            padding: 20px 30px;
                        }

                        h1 {
                            margin: 10px 0 20px 0;
                        }

                        .center {
                            text-align: center;
                        }

                        .btn-group {
                            margin: 10px 0 0 0;
                            display: flex;
                            text-align: center;
                        }

                        .btn {
                            margin: 0 10px 0px 10px;
                        }
                    </style>
                </custom-style>
                <h1 class="center">Completed Part</h1>
                <paper-input label="No. of Good" id="goodCount" value="{{good}}" type="number" always-float-label></paper-input>
                <paper-input label="No. of Defect" id="defectCount" value="{{defect}}" type="number" always-float-label></paper-input>
                <div class="btn-group">
                    <paper-button dialog-dismiss on-click="closeJobDialog">
                        {{localize('dismiss')}}
                    </paper-button>
                    <paper-button dialog-confirm autofocus on-click="updateFinish">
                        {{localize('save')}}
                    </paper-button>
                </div>
            </template>
        </vaadin-dialog>

    </template>
    <script>
        /**
         * @ViewTrackProduction
         * @polymer 
         * @extends {Polymer.Element}
         * @polymerBehavior Polymer.AppLocalizeBehavior
         */
        class ViewTrackProduction extends Polymer.mixinBehaviors([Polymer.AppLocalizeBehavior],
            Polymer.Element) {
            static get is() {
                return 'view-track-production';
            }

            static get properties() {
                return {
                    selectedStation: {
                        type: String,
                        reflectToAttribute: true,
                        value: 1
                    },
                    language: String,
                    orderHistoryData: Object,
                    orderItems: Object,
                    trackingItems: Object,
                    warehouseItems: {
                        type: Object,
                        notify: true,
                    },
                    deviceItems: {
                        type: Object,
                        computed: ''
                    },
                    defect: {
                        type: Number,
                        value: 0
                    }
                }
            }

            static get observers() {
                return [
                    '_updateOrderTable(warehouseItems)'
                ]
            }

            connectedCallback() {
                super.connectedCallback()
                this.loadResources(this.resolveUrl('../../data/locales.json'))
            }

            ready() {
                super.ready()
                this._checkJobStatus()
            }
            removeJob(e) {
                if (window.confirm("Remove this job?") == true) {
                    const key = e.currentTarget.job.$key;
                    this.$.trackingQuery.ref.child(key).remove();
                }
            }

            openJobDialog(e) {
                this.$.reportJobDialog.opened = true;
                this.selectedJob = e.currentTarget.job;
            }

            closeJobDialog() {
                this.$.reportJobDialog.opened = false;
                Polymer.dom(this.$.reportJobDialog).querySelectorAll('#goodCount').value = ''
                this.good = ''
            }

            receiveJob(e) {
                this.$.trackingQuery.ref.child(e.currentTarget.job.$key).update({
                    actual_start: Math.round(new Date().getTime() / 1000.0),
                    job_status: 'wip'
                })
            }

            updateFinish() {
                if (!this.defect) this.defect = 0;
                if (parseInt(this.good) >= this.selectedJob.job_quantity) {
                    this.$.trackingQuery.ref.child(this.selectedJob.$key).update({
                        actual_end: Math.round(new Date().getTime() / 1000.0),
                        job_status: 'done',
                        job_complete: this.getCompleteProgress(this.good, this.selectedJob.job_quantity),
                        job_defect: parseInt(this.defect),
                        job_good: parseInt(this.good) || (this.selectedJob.job_quantity - this.defect) // output of station
                    }).then(this._checkJobStatus())
                } else {
                    this.$.trackingQuery.ref.child(this.selectedJob.$key).update({
                        job_complete: this.getCompleteProgress(this.good, this.selectedJob.job_quantity),
                        job_defect: parseInt(this.defect),
                        job_good: parseInt(this.good) || (this.selectedJob.job_quantity - this.defect) // output of station
                    }).then(this._checkJobStatus())
                }
                this.$.reportJobDialog.opened = false;
                this.selectedJob = '';
            }

            getActualDuration(start, end) {
                if (start && end) {
                    const diff = end - start;
                    return this.secondsToHms(diff);
                }
                return 0
            }

            isEmptyJobs(length) {
                return (length > 0)
            }

            filterByStation(station) {
                if (!station) {
                    // set filter to null to disable filtering
                    return null;
                } else {
                    let filterData = ((trackingItems) => {
                        return trackingItems.job_station == station
                    });
                    return filterData;
                }
            }

            _checkJobStatus() {
                if (!this.trackingItems) return
                // 1) group by order_no as an array
                const order_group = this.trackingItems.reduce((r, a) => {
                    r[a.order_no] = r[a.order_no] || [];
                    r[a.order_no].push(a);
                    return r;
                }, []);

                const arr = Object.values(this.trackingItems)
                const unique = (v, i, a) => a.indexOf(v) === i
                const productNames = arr.map(product => product.order_product).filter(unique)
                const groupByName = productNames.map(name => arr.filter(product => product.order_product ===
                    name))

                // 2) condition to filter order_status == done
                let isStatusDone = ((element) => {
                    return (element.job_status === 'done')
                })

                // 3) check that element job_status of every item is == done
                let done_order = [];
                if (order_group) {
                    order_group.map((key, i) => {
                        if (order_group[i].every(isStatusDone)) {
                            done_order.push(order_group[i]);
                        }
                    })
                }

                // 4) if every jobs in order is done so push to done_order 
                if (done_order.length > 0) {
                    let warehouse_order;

                    for (let i = 0; i < done_order.length; i++) {
                        warehouse_order = done_order[i].map((value, index, arr) => {
                            return {
                                order_delivery: value.order_delivery,
                                order_customer: value.order_customer,
                                order_product: value.order_product,
                                order_color: value.order_color,
                                order_good: value.job_good,
                                order_quantity: value.job_quantity,
                                order_no: value.order_no,
                                order_defect: parseInt(value.job_defect),
                                job_station: value.job_station,
                                plan_duration: (value.end - value.start),
                                actual_duration: (value.actual_end - value.actual_start),
                            };
                        });
                    }
                    //console.log(warehouse_order)

                    // 5.1) Sum actual duration of all jobs 
                    let sum_actual_duration = warehouse_order.reduce((a, b) =>
                        a + b.actual_duration, 0)
                    //console.log(sum_actual_duration)

                    // 5.2) Sum plan duration of all jobs 
                    let sum_plan_duration = warehouse_order.reduce((a, b) =>
                        a + b.plan_duration, 0)
                    //console.log(sum_plan_duration)

                    // 5.3) Sum defect of all jobs 
                    let sum_defect = warehouse_order.reduce((a, b) =>
                        a + b.order_defect, 0)
                    //console.log(sum_defect)

                    // 6) Remove duplicate order no from array export single
                    let filterDoneOrder = warehouse_order
                        .map(o => o.order_no)
                        .filter((item, index, inputArray) => inputArray.indexOf(item) == index)

                    // 7) Update order no table
                    for (let j = 0; j < filterDoneOrder.length; j++) {
                        this._updateOrderTable(filterDoneOrder[j]);
                    }

                    // 8) Covert data to array 
                    let exportData = warehouse_order.reduce((a, b) => a.concat(b), []);

                    // 9) Convert data to object with match key
                    let resultObject = exportData.reduce((result, currentObject) => {
                        for (let key in currentObject) {
                            if (currentObject.hasOwnProperty(key)) {
                                result[key] = currentObject[key];
                            }
                        }
                        return result;
                    }, {});

                    // 10) Delete key that can't add to firebase and replace with default index
                    delete resultObject.$key

                    // 11) Update order information from all jobs
                    resultObject.order_defect = sum_defect
                    resultObject.plan_duration = sum_plan_duration
                    resultObject.actual_duration = sum_actual_duration
                    console.log(resultObject)

                    // 12) If not duplicate in warehouse add order to warehouse
                    let isDuplicated = this.warehouseItems.map(item => item.order_no).indexOf(resultObject.order_no) >
                        -1
                    if (!isDuplicated) {
                        this._addToWarehouse(resultObject)
                    }
                }
            }

            _checkJobDependency() {

            }
            
            _addToWorkCommit() {
                let currentDay = daysOfTheYear() - 1;
                this.$.commitQuery.ref.child('/' + currentDay).once("value", (snapshot) => {
                    if (snapshot.val()) {
                        this.todayCommit = snapshot.val().commit + 1
                        if (this.todayCommit <= 0) {
                            this.todayLevel = 0
                        } else if (this.todayCommit >= 1 && this.todayCommit < 3) {
                            this.todayLevel = 1
                        } else if (this.todayCommit >= 3 && this.todayCommit < 5) {
                            this.todayLevel = 2
                        } else if (this.todayCommit >= 5 && this.todayCommit < 7) {
                            this.todayLevel = 3
                        } else if (this.todayCommit >= 7) {
                            this.todayLevel = 4
                        }
                    }
                })
                this.$.commitQuery.ref.child('/' + currentDay).update({
                    commit: this.todayCommit,
                    level: this.todayLevel
                })
            }

            _addToWarehouse(data) {
                if (data) {
                    this.$.warehouseQuery.ref.push(data)
                    // TODO: add notification 
                    this._addToWorkCommit()
                }
            }

            _updateOrderTable(warehouse) {
                if (warehouse.length > 0) {
                    this.warehouseItems.map((data) => {
                        this.$.orderQuery.ref.orderByChild("order_no").equalTo(data.order_no).once(
                            "value", (snapshot) => {
                                if (snapshot.val() !== null) {
                                    let key = Object.keys(snapshot.val())[0]
                                    snapshot.ref.child(key).update({
                                        order_status: "done"
                                    })
                                }
                            })
                    })
                }
            }

            secondsToHms(sec) {
                sec = Number(sec);
                const h = Math.floor(sec / 3600);
                const m = Math.floor(sec % 3600 / 60);
                const s = Math.floor(sec % 3600 % 60);
                return ('0' + h).substr(-2) + ':' + ('0' + m).substr(-2) + ':' + ('0' + s).substr(-2);
            }

            timestampToTime(timestamp) {
                if (!timestamp) return 'N/A'
                const date = new Date((timestamp) * 1000);
                const h = date.getHours();
                const m = date.getMinutes();
                const s = date.getSeconds();
                const dd = date.getDate();
                const mm = date.getMonth() + 1;
                const yy = date.getFullYear();
                return ('0' + h).substr(-2) + ':' + ('0' + m).substr(-2) + ' ' + dd + '/' + mm + '/' + yy
            }

            resetCounter(e) {
                const key = e.currentTarget.device.$key;
                this.$.deviceQuery.ref.child(key).update({
                    counter: 0,
                    update: Math.round(new Date().getTime() / 1000.0)
                })
            }

            isDone(status) {
                return (status === 'done' || status === 'waiting')
            }

            isDoneOrWIP(status) {
                return (status === 'wip' || status === 'done')
            }

            getMinuteToStr(minute) {
                const sec = Number(minute*60);
                let sign = '';
                let hours = this._leftPad(Math.floor(Math.abs(sec) / 3600));
                let minutes = this._leftPad(Math.round(Math.abs(sec) % 3600 / 60));
                let seconds = this._leftPad(Math.round(Math.abs(sec) % 3600 % 60));
                return hours + 'hr. ' + minutes + 'min.' + seconds + 's.';
            }

             // ADD 0 to numbers less than 10,Eg: 2 -> 02 
             _leftPad(number) {
                return ((number < 10 && number >= 0) ? '0' : '') + number;
            }
            
            getColorStatus(job_status) {
                switch (job_status) {
                    case 'waiting':
                        return '#FFB300'
                        break;
                    case 'wip':
                        return '#5E35B1'
                        break;
                    case 'done':
                        return '#7CB342'
                        break;
                    case 'late':
                        return '#E53935'
                        break;
                    case 'cancel':
                        return '#E53935'
                        break;
                    default:
                        return '#202020'
                }
            }

            getTextStatus(job_status) {
                return job_status === 'wip' ? 'blink' : 'normal'
            }

            getCompleteProgress(job_good, job_quantity) {
                return ((job_good * 100) / job_quantity).toFixed(2)
            }

            getDeviceCounter(item, quantity, selectDevice) {
                if (!selectDevice) return 0
                const query = this.$.deviceQuery.ref;
                let count = 0;
                query.child("/" + selectDevice.$key + "/counter").once("value", (snapshot) => {
                    if (snapshot.val()) {
                        count = snapshot.val()
                    }
                });
                if (count >= quantity) {
                    this.$.trackingQuery.ref.child(item.$key).update({
                        actual_end: Math.round(new Date().getTime() / 1000.0),
                        job_status: 'done',
                        job_defect: 0,
                        job_good: count // output of station
                    })
                }
                return count
            }

            removeDevice(e) {
                if (window.confirm("Remove this device?") == true) {
                    const key = e.currentTarget.device.$key;
                    this.$.deviceQuery.ref.child(key).remove();
                }
            }

            openAddDeviceCard() {

            }
        }
        customElements.define(ViewTrackProduction.is, ViewTrackProduction);
    </script>
</dom-module>